package com.devo.icecream.ui.widget

import android.graphics.Paint
import android.graphics.Rect
import androidx.annotation.FloatRange
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.*
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.material.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.*
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Path
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.drawscope.drawIntoCanvas
import androidx.compose.ui.graphics.drawscope.translate
import androidx.compose.ui.graphics.nativeCanvas
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.devo.icecream.ui.theme.IcecreamTheme

private val textPaint = Paint()

@Composable
fun MakingProgressBar(
    modifier: Modifier = Modifier,
    progress: Float = 0.6f,
    color: Color = Color.Red,
    backgroundColor: Color = Color(0x88909090),
    progressHeight: Dp = 16f.dp,
    textColor: Color = Color.White,
    textSize: TextUnit = 14f.sp
) {
    val progressValue by remember(progress) {
        mutableStateOf(progress)
    }

    val progressState = animateFloatAsState(targetValue = progressValue)

    val progressHeightPx = with(LocalDensity.current) {
        progressHeight.toPx()
    }

    val progressCornerRadius = CornerRadius(progressHeightPx / 2, progressHeightPx / 2)

    Canvas(modifier = Modifier
        .wrapContentHeight()
        .then(modifier)) {
        val (width, height) = size
        val offset = Offset(0f, (height - progressHeightPx) / 2f)
        drawRoundRect(
            color = backgroundColor,
            topLeft = offset,
            size = size.copy(height = progressHeightPx),
            cornerRadius = progressCornerRadius
        )

        drawRoundRect(
            color = color,
            topLeft = offset,
            size = size.copy(width = width * progress, height = progressHeightPx),
            cornerRadius = progressCornerRadius
        )

        translate(top = (height + progressHeightPx) / 2 + 2f, left = width * progressState.value) {
            drawProgressTag(
                process = progressState.value,
                color = color,
                textColor = textColor,
                textSize = textSize
            )
        }

    }
}

private const val textPaddingPx = 10f
private const val textPaddingHorizontalRate = 4f
private const val textPaddingVerticalRate = 2f
private val textRect = Rect()
private fun DrawScope.drawProgressTag(
    @FloatRange(from = 0.0, to = 1.0) process: Float = 0.5f,
    color: Color = Color.Red,
    textColor: Color = Color.White,
    textSize: TextUnit = 30f.sp
) {
    val progressText = "${(100 * process).toInt()}%"
    textPaint.apply {
        isAntiAlias = true
        style = Paint.Style.FILL
        this.textSize = textSize.toPx()
        this.color = textColor.toArgb()
    }

    textPaint.getTextBounds(progressText, 0, progressText.length, textRect)
    val size = Size(
        width = textRect.width() + textPaddingPx * textPaddingHorizontalRate,
        height = textRect.height() + textPaddingPx * textPaddingVerticalRate
    )
    val triangleWidth = size.width / 3f
    val triangleHeight = triangleWidth * 0.6f
    translate(left = -(size.width / 2)) {

        drawPath(
            path = Path().apply {
                addPath(
                    Path().apply {
                        moveTo(triangleWidth / 2, 0f)
                        lineTo(triangleWidth, triangleHeight)
                        lineTo(0f, triangleHeight)
                    },
                    Offset((size.width - triangleWidth) / 2f, 0f)
                )
                addRoundRect(
                    RoundRect(
                        rect = Rect(
                            0f,
                            triangleHeight,
                            size.width,
                            size.height + triangleHeight
                        ),
                        radiusX = 10f,
                        radiusY = 10f
                    )
                )
            },
            color = color
        )

        translate(
            top = triangleHeight + textPaddingPx,
            left = textPaddingPx * textPaddingHorizontalRate / 2
        ) {
            drawText(
                progressText,
                0f,
                textRect.height().toFloat(),
                textPaint.apply {
                    isAntiAlias = true
                    style = Paint.Style.FILL
                    this.textSize = textSize.toPx()
                    this.color = textColor.toArgb()
                }
            )
        }
    }

}

private fun DrawScope.drawEqTriangle(
    width: Float,
    height: Float,
    color: Color = Color.Black
) {
    drawPath(
        path = Path().apply {
            moveTo(width / 2, 0f)
            lineTo(width, height)
            lineTo(0f, height)
        },
        color = color
    )

}

fun DrawScope.drawText(text: String, x: Float = 0f, y: Float = 0f, paint: Paint = textPaint) {
    drawIntoCanvas {
        it.nativeCanvas.drawText(text, x, y, paint)
    }
}

@Preview
@Composable
private fun Preview() {
    IcecreamTheme() {

        val progress = remember {
            mutableStateOf(0.1f)
        }

        Column(
            modifier = Modifier.fillMaxSize(),
            horizontalAlignment = Alignment.CenterHorizontally
        ) {


            MakingProgressBar(
                progress = progress.value,
                modifier = Modifier
                    .fillMaxWidth()
                    .height(100.dp)
            )


            Surface(color = Color.Red) {
                TextButton(onClick = { progress.value = (progress.value + 0.1f) % 1 }) {
                    Text(text = "点击增长")
                }
            }

        }


    }
}